package service.TCPService;

import codec.DemoProtocolCodec;
import codec.MsgDecode;
import codec.MsgEncode;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.bytes.ByteArrayDecoder;
import io.netty.handler.codec.bytes.ByteArrayEncoder;
import io.netty.handler.timeout.IdleStateHandler;
import org.apache.log4j.Logger;

import java.util.concurrent.TimeUnit;


/**
 * Created by momochen on 2017-07-18.
 */
public class NettyTCPServerBootstrap {
    private static Logger logger = Logger.getLogger(NettyTCPServerBootstrap.class);
    //默认端口号
    private int port = 8088;

    private volatile EventLoopGroup bossGroup = new NioEventLoopGroup();
    private volatile EventLoopGroup workGroup = new NioEventLoopGroup(10);

    private volatile ChannelFuture channelFuture;

    public NettyTCPServerBootstrap(int port) {
        this.port = port;
        bind();
    }

    private void bind() {
        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workGroup);
            bootstrap.channel(NioServerSocketChannel.class);
            //通过NoDelay禁用Nagle,使消息立即发出去，不用等待到一定的数据量才发出去
            bootstrap.option(ChannelOption.TCP_NODELAY, true);
            bootstrap.option(ChannelOption.SO_BACKLOG, 1024); // 设置tcp缓冲区
//            bootstrap.option(ChannelOption.SO_SNDBUF, 32 * 1024); // 设置发送缓冲大小
//            bootstrap.option(ChannelOption.SO_RCVBUF, 32 * 1024); // 这是接收缓冲大小
            //保持长连接状态
            bootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);
            bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel socketChannel) throws Exception {
                    ChannelPipeline p = socketChannel.pipeline();
                    p.addLast(new IdleStateHandler(0, 0, 60, TimeUnit.SECONDS));
//                    p.addLast(new MsgDecode());
//                    p.addLast(new MsgEncode());
                    p.addLast(new DemoProtocolCodec());
                    p.addLast(new NettyTCPServiceHandler());
                }
            });

            channelFuture = bootstrap.bind(port).sync();
            if (channelFuture.isSuccess()) {
                System.out.println("TCPServer start success Port:" + this.port);
                logger.info("TCPServer start success Port:" + this.port);
            } else {
                logger.info("TCPServer start failure Port:" + this.port);
                System.out.println("TCPServer start failure Port:" + this.port);
            }
            channelFuture.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            Runtime.getRuntime().addShutdownHook(new Thread(() -> shutdown()));
        }
    }

    /**
     * 关闭
     */
    public void shutdown() {
        if (channelFuture != null && channelFuture.channel() != null) {
            channelFuture.channel().close().syncUninterruptibly();
        }
        if (bossGroup != null) {
            bossGroup.shutdownGracefully();
        }
        if (workGroup != null) {
            workGroup.shutdownGracefully();
        }
    }
}
